home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 February: Tool Chest / Apple Developer CD Series Tool Chest February 1996 (Apple Computer)(1996).iso / Sample Code / Snippets / QuickDraw / CalcCMask & CalcMask / CalcCMask & CalcMask.c next >
Encoding:
C/C++ Source or Header  |  1992-07-15  |  6.8 KB  |  251 lines  |  [TEXT/KAHL]

  1. /****************************************************************************/
  2. /*                                                                            */
  3. /*    Application:    CalcCMask & CalcMask                                    */
  4. /*                                                                            */
  5. /*    Description:    This snippet shows how to use both CalcCMask or            */
  6. /*                    CalcMask to create a mask given a source bitmap            */
  7. /*                    image.  As decribed on pages IV-24 and V-72 of            */
  8. /*                    Inside Mac, the two routines compute a destination        */
  9. /*                    bitmap image with 1's only in the pixels where            */
  10. /*                    paint can not leak from any of the outer edges.            */
  11. /*                    This is similar to the lasso tool found in many            */
  12. /*                    drawing apps.                                            */
  13. /*                                                                            */
  14. /*    File:            CalcCMask & CalcMask.π                                    */
  15. /*                    CalcCMask & CalcMask.c                                    */
  16. /*                    CalcCMask & CalcMask.π.rsrc                                */
  17. /*                                                                            */
  18. /*    Programmer:        Edgar Lee                                                */
  19. /*    Organization:    Apple Computer, Inc.                                    */
  20. /*    Department:        Developer Technical Support, DTS                        */
  21. /*    Language:        C (Think C version 5.0.1)                                */
  22. /*    Date Created:    2-26-92                                                    */
  23. /*                                                                            */
  24. /****************************************************************************/
  25.  
  26. /* Constant Declarations */
  27.  
  28. #define    WWIDTH        176
  29. #define    WHEIGHT        106
  30.  
  31. #define WLEFT        (((screenBits.bounds.right - screenBits.bounds.left) - WWIDTH) / 2)
  32. #define WTOP        (((screenBits.bounds.bottom - screenBits.bounds.top) - WHEIGHT) / 2)
  33.  
  34. /* Global Variable Definitions */
  35.  
  36. WindowPtr    gWindow;
  37.  
  38. void initMac();
  39. void createWindow();
  40. void doCalcCMaskExample();
  41.  
  42. void DisposeGrafPort();
  43. GrafPtr CreateGrafPort();
  44.  
  45. void doEventLoop();
  46.  
  47. main()
  48. {
  49.     initMac();
  50.     
  51.     createWindow();
  52.     
  53.     doEventLoop();
  54. }
  55.  
  56. void initMac()
  57. {
  58.     MaxApplZone();
  59.     
  60.     InitGraf( &thePort );
  61.     InitFonts();
  62.     InitWindows();
  63.     InitMenus();
  64.     TEInit();
  65.     InitDialogs( nil );
  66.     InitCursor();
  67.     FlushEvents( 0, everyEvent );
  68. }
  69.  
  70. void createWindow()
  71. {
  72.     Rect rect;
  73.     
  74.     SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  75.     
  76.     gWindow = NewCWindow( 0L, &rect, "\pCalc-C-Mask", true, documentProc,
  77.                             (WindowPtr)-1L, true, 0L );
  78.                             
  79.     SetPort( gWindow );
  80. }
  81.  
  82. #define    COLOR_VERSION
  83.  
  84. void doCalcCMaskExample()
  85. {
  86.     PicHandle    pict;                /* B/W Pict used to create mask. */
  87.     GWorldPtr    gworld;                /* Gworld used for CopyMask source. */
  88.     GrafPtr     mask;                /* Mask created by CalcCMask. */
  89.     GrafPtr        sourceForMask;        /* Bitmap of pict image used for creating mask. */
  90.     RGBColor    seedColor;            /* Color used to determine the mask. */
  91.     Rect        rect;                /* Bounding rect of mask and source. */
  92.     CGrafPtr    currentPort;        /* Saved CGrafPtr for later restore. */
  93.     GDHandle    currentDevice;        /* Saved device for later restore. */
  94.     
  95.     /* Load the pict resource to be used for the mask. */
  96.     pict = (PicHandle)GetResource( 'PICT', 128 );
  97.     
  98.     /* Define the bounding rect for the source and mask bitmap. */
  99.     rect = (**pict).picFrame;
  100.     OffsetRect( &rect, -rect.left, -rect.top );
  101.     
  102.     /* Allocate the source bitmap for which the mask will be created from. */
  103.     sourceForMask = CreateGrafPort( &rect );
  104.     
  105.     /* Create the source bitmap's image by using the pict. */
  106.     SetPort( sourceForMask );
  107.     DrawPicture( pict, &rect );
  108.     SetPort( gWindow );
  109.     
  110.     /* Release the memory used by the pict. */
  111.     ReleaseResource( pict );
  112.  
  113.     /* Create a gworld of a blue rectangle for the CopyMask source. */
  114.     GetGWorld( ¤tPort, ¤tDevice );
  115.     NewGWorld( &gworld, 8, &rect, nil, nil, 0 );
  116.     SetPort( gworld );
  117.     ForeColor( blueColor );
  118.     PaintRect( &rect );
  119.     SetGWorld( currentPort, currentDevice );
  120.     
  121.     /* Copy the source image to the window to see what the mask was created from. */
  122.     CopyBits( &sourceForMask->portBits, &gWindow->portBits,
  123.                 &sourceForMask->portRect, &rect, srcCopy, nil );
  124.     
  125.     /* Allocate the bitmap for the mask. */
  126.     mask = CreateGrafPort( &sourceForMask->portRect );
  127.  
  128. #ifdef COLOR_VERSION
  129.  
  130.     /* Create a mask from the source bitmap of all colors that match the seedColor. */
  131.     seedColor.red = seedColor.green = seedColor.blue = 0;
  132.     
  133.     CalcCMask( &sourceForMask->portBits, &mask->portBits, &sourceForMask->portRect,
  134.                 &mask->portRect, &seedColor, nil, 0 );
  135.  
  136. #else
  137.  
  138.     CalcMask( &sourceForMask->portBits.baseAddr, &mask->portBits.baseAddr,
  139.                 sourceForMask->portBits.rowBytes, mask->portBits.rowBytes,
  140.                 sourceForMask->portRect.bottom - sourceForMask->portRect.top,
  141.                 sourceForMask->portBits.rowBytes >> 1 );
  142.  
  143. #endif
  144.  
  145.     /* Now draw the blue rectangle with its mask. */
  146.     OffsetRect( &rect, sourceForMask->portRect.right, 0 );
  147.     CopyMask( &(*gworld).portPixMap, &mask->portBits, &gWindow->portBits,
  148.                 &sourceForMask->portRect, &mask->portRect, &rect );
  149.  
  150.     /* Release the used memory. */
  151.     DisposeGrafPort( sourceForMask );
  152.     DisposeGrafPort( mask );
  153.     DisposeGWorld( gworld );
  154. }
  155.  
  156. GrafPtr CreateGrafPort( bounds )    /* Originally written by Forrest Tanaka. */
  157. Rect *bounds;
  158. {
  159.     GrafPtr    savedPort;        /* Saved GrafPtr for later restore. */
  160.     GrafPtr    newPort;        /* New GrafPort. */
  161.     Rect    localBounds;    /* Local copy of bounds. */
  162.  
  163.     GetPort( &savedPort );
  164.  
  165.     /* Set the top-left corner of bounds to (0,0). */
  166.     localBounds = *bounds;
  167.     OffsetRect( &localBounds, -bounds->left, -bounds->top );
  168.  
  169.     /* Allocate a new GrafPort. */
  170.     newPort = (GrafPtr)NewPtrClear( sizeof( GrafPort ) );
  171.     
  172.     if (newPort != nil)
  173.     {
  174.         /* Initialize the new port and make the current port. */
  175.         OpenPort( newPort );
  176.  
  177.         /* Initialize and allocate the bitmap. */
  178.         newPort->portBits.bounds = localBounds;
  179.           newPort->portBits.rowBytes = ((localBounds.right + 15) >> 4) << 1;
  180.         newPort->portBits.baseAddr =  NewPtrClear( newPort->portBits.rowBytes *
  181.                                                     (long)localBounds.bottom );
  182.         if (newPort->portBits.baseAddr != nil)
  183.         {
  184.             /* Clean up the new port. */
  185.             newPort->portRect = localBounds;
  186.             ClipRect( &localBounds );
  187.             RectRgn( newPort->visRgn, &localBounds );
  188.             EraseRect( &localBounds );
  189.         }
  190.         else
  191.         {
  192.             /* Allocation failed; deallocate the port. */
  193.             ClosePort( newPort );
  194.             DisposPtr( (Ptr)newPort );
  195.             newPort = nil;
  196.         }
  197.     }
  198.     
  199.     SetPort( savedPort );
  200.     return newPort;
  201. }
  202.  
  203. void DisposeGrafPort( doomedPort )        /* Originally written by Forrest Tanaka. */
  204. GrafPtr doomedPort;
  205. {
  206.     ClosePort( doomedPort );
  207.     DisposPtr( doomedPort->portBits.baseAddr );
  208.     DisposPtr( (Ptr)doomedPort );
  209. }
  210.  
  211. void doEventLoop()
  212. {
  213.     EventRecord event;
  214.     WindowPtr   window;
  215.     short       clickArea;
  216.     Rect        screenRect;
  217.  
  218.     for (;;)
  219.     {
  220.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  221.         {
  222.             if (event.what == mouseDown)
  223.             {
  224.                 clickArea = FindWindow( event.where, &window );
  225.                 
  226.                 if (clickArea == inDrag)
  227.                 {
  228.                     screenRect = (**GetGrayRgn()).rgnBBox;
  229.                     DragWindow( window, event.where, &screenRect );
  230.                 }
  231.                 else if (clickArea == inContent)
  232.                 {
  233.                     if (window != FrontWindow())
  234.                         SelectWindow( window );
  235.                 }
  236.                 else if (clickArea == inGoAway)
  237.                     if (TrackGoAway( window, event.where ))
  238.                         return;
  239.             }
  240.             else if (event.what == updateEvt)
  241.             {
  242.                 window = (WindowPtr)event.message;    
  243.                 SetPort( window );
  244.                 
  245.                 BeginUpdate( window );
  246.                 doCalcCMaskExample();
  247.                 EndUpdate( window );
  248.             }
  249.         }
  250.     }
  251. }